Plug GtkATContext into GtkAccessible
authorEmmanuele Bassi <ebassi@gnome.org>
Wed, 8 Jul 2020 15:56:31 +0000 (16:56 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Sun, 26 Jul 2020 19:31:14 +0000 (20:31 +0100)
An Accessible implementation must create an ATContext object. UI
elements are supposed to interact with the GtkAccessible API, but we
expose GtkATContext to allow patterns like delegation.

gtk/gtkaccessible.c
gtk/gtkaccessible.h
gtk/gtkaccessibleprivate.h [new file with mode: 0644]

index d8187b60c0ad4065c39677073eccb4d8d0d57489..c6e576c32951255b7c1c32470711f117ce8552bd 100644 (file)
  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
+/**
+ * SECTION:gtkaccessible
+ * @Title: GtkAccessible
+ * @Short_description: Accessible interface
+ *
+ * GtkAccessible provides an interface for describing a UI element, like a
+ * #GtkWidget, in a way that can be consumed by Assistive Technologies, or
+ * “AT”. Every accessible implementation has:
+ *
+ *  - a “role”, represented by a value of the #GtkAccessibleRole enumeration
+ *  - a “state”, represented by a set of #GtkAccessibleState and
+ *    #GtkAccessibleProperty values
+ *
+ * The role cannot be changed after instantiating a #GtkAccessible
+ * implementation.
+ *
+ * The state is updated every time a UI element's state changes in a way that
+ * should be reflected by assistive technologies. For instance, if a #GtkWidget
+ * visibility changes, the %GTK_ACCESSIBLE_STATE_HIDDEN state will also change
+ * to reflect the #GtkWidget:visible property.
+ */
+
 #include "config.h"
 
-#include "gtkaccessible.h"
+#include "gtkaccessibleprivate.h"
+
+#include "gtkatcontextprivate.h"
+#include "gtkenums.h"
+
+#include <stdarg.h>
 
 G_DEFINE_INTERFACE (GtkAccessible, gtk_accessible, G_TYPE_OBJECT)
 
@@ -28,3 +55,97 @@ static void
 gtk_accessible_default_init (GtkAccessibleInterface *iface)
 {
 }
+
+GtkATContext *
+gtk_accessible_get_at_context (GtkAccessible *self)
+{
+  g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL);
+
+  return GTK_ACCESSIBLE_GET_IFACE (self)->get_at_context (self);
+}
+
+/**
+ * gtk_accessible_update_state:
+ * @self: a #GtkAccessible
+ * @first_state: the first #GtkAccessibleState
+ * @...: a list of state and value pairs, terminated by %GTK_ACCESSIBLE_STATE_NONE
+ *
+ * Updates a list of accessible states.
+ *
+ * This function should be called by #GtkWidget types whenever an accessible
+ * state change must be communicated to assistive technologies.
+ */
+void
+gtk_accessible_update_state (GtkAccessible *self,
+                             GtkAccessibleState  first_state,
+                             ...)
+{
+  GtkAccessibleState state;
+  GtkATContext *context;
+  va_list args;
+
+  g_return_if_fail (GTK_IS_ACCESSIBLE (self));
+
+  context = gtk_accessible_get_at_context (self);
+  if (context == NULL)
+    return;
+
+  va_start (args, first_state);
+
+  state = first_state;
+
+  while (state != GTK_ACCESSIBLE_STATE_NONE)
+    {
+      GtkAccessibleValue *value = gtk_accessible_value_collect_for_state (state, &args);
+
+      if (value == NULL)
+        goto out;
+
+      gtk_at_context_set_state (context, state, value);
+      gtk_accessible_value_unref (value);
+
+      state = va_arg (args, int);
+    }
+
+  gtk_at_context_update_state (context);
+
+out:
+  va_end (args);
+}
+
+/**
+ * gtk_accessible_update_state_value:
+ * @self: a #GtkAccessible
+ * @state: a #GtkAccessibleState
+ * @value: a #GValue with the value for @state
+ *
+ * Updates an accessible state.
+ *
+ * This function should be called by #GtkWidget types whenever an accessible
+ * state change must be communicated to assistive technologies.
+ *
+ * This function is meant to be used by language bindings.
+ */
+void
+gtk_accessible_update_state_value (GtkAccessible      *self,
+                                   GtkAccessibleState  state,
+                                   const GValue       *value)
+{
+  GtkATContext *context;
+
+  g_return_if_fail (GTK_IS_ACCESSIBLE (self));
+
+  context = gtk_accessible_get_at_context (self);
+  if (context == NULL)
+    return;
+
+  GtkAccessibleValue *real_value =
+    gtk_accessible_value_collect_for_state_value (state, value);
+
+  if (real_value == NULL)
+    return;
+
+  gtk_at_context_set_state (context, state, real_value);
+  gtk_accessible_value_unref (real_value);
+  gtk_at_context_update_state (context);
+}
index d54d21a2d07fa3fa9c73db5e56968657b1f94df2..9fe16616e5ce3d4c968af4509ae66f535aa98a2e 100644 (file)
@@ -31,9 +31,13 @@ G_BEGIN_DECLS
 GDK_AVAILABLE_IN_ALL
 G_DECLARE_INTERFACE (GtkAccessible, gtk_accessible, GTK, ACCESSIBLE, GObject)
 
-struct _GtkAccessibleInterface
-{
-  GTypeInterface g_iface;
-};
+GDK_AVAILABLE_IN_ALL
+void    gtk_accessible_update_state             (GtkAccessible      *self,
+                                                 GtkAccessibleState  first_state,
+                                                 ...);
+GDK_AVAILABLE_IN_ALL
+void    gtk_accessible_update_state_value       (GtkAccessible      *self,
+                                                 GtkAccessibleState  state,
+                                                 const GValue       *value);
 
 G_END_DECLS
diff --git a/gtk/gtkaccessibleprivate.h b/gtk/gtkaccessibleprivate.h
new file mode 100644 (file)
index 0000000..aa5701c
--- /dev/null
@@ -0,0 +1,37 @@
+/* gtkaccessibleprivate.h: Accessible interface
+ *
+ * Copyright 2020  GNOME Foundation
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "gtkaccessible.h"
+#include "gtkatcontext.h"
+
+G_BEGIN_DECLS
+
+struct _GtkAccessibleInterface
+{
+  GTypeInterface g_iface;
+
+  GtkATContext *        (* get_at_context)      (GtkAccessible *self);
+};
+
+GtkATContext *  gtk_accessible_get_at_context   (GtkAccessible *self);
+
+G_END_DECLS